using Microsoft.Extensions.Logging;
using PowerManage.Entity;
using PowerManage.Entity.Dtos.AudiLogs;
using PowerManage.Repository;

namespace PowerManage.Service.Impl;

public class AuditLogService : BaseService, IAuditLogService
{
    private readonly IBaseRepository<EleAuditLog> _auditLogRepository;
    private readonly ILogger<AuditLogService> _logger;
    private readonly IBaseRepository<EleUser> _userRepository;

    /// <summary>
    /// 构造器注入
    /// </summary>
    /// <param name="auditLogRepository"></param>
    /// <param name="logger"></param>
    public AuditLogService(IBaseRepository<EleAuditLog> auditLogRepository, ILogger<AuditLogService> logger,
        IBaseRepository<EleUser> userRepository)
    {
        _auditLogRepository = auditLogRepository;
        _logger = logger;
        _userRepository = userRepository;
    }

    /// <summary>
    /// 插入审核日志
    /// </summary>
    /// <param name="eleAuditLog"></param>
    /// <returns></returns>
    public EleAuditLog Add(EleAuditLog eleAuditLog)
    {
        try
        {
            return _auditLogRepository.Add(eleAuditLog);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "保存日志至数据库异常，接口：{0}\r\nMethod：{1}\r\n参数：{2}\r\nIP：{3}\r\n花费时长：{4}", eleAuditLog.ApiUrl,
                eleAuditLog.Method, eleAuditLog.Parameters, eleAuditLog.ClientIpAddress, eleAuditLog.ExecutionDuration);
            return eleAuditLog;
        }
    }

    /// <summary>
    /// 获取审核日志列表
    /// </summary>
    /// <param name="audiLogPageRequestDto"></param>
    /// <returns></returns>
    public AuditLogPageResponseDto Query(AudiLogPageRequestDto audiLogPageRequestDto)
    {
        var result = new AuditLogPageResponseDto();
        var auditLogQuery = _auditLogRepository.GetQueryable();
        if (!string.IsNullOrEmpty(audiLogPageRequestDto.ApiUrl))
        {
            auditLogQuery = auditLogQuery.Where(x => x.ApiUrl.Contains(audiLogPageRequestDto.ApiUrl));
        }

        if (!string.IsNullOrEmpty(audiLogPageRequestDto.ClientIpAddress))
        {
            auditLogQuery = auditLogQuery.Where(x => x.ClientIpAddress.Equals(audiLogPageRequestDto.ClientIpAddress));
        }

        if (audiLogPageRequestDto.StartTime.HasValue)
        {
            auditLogQuery = auditLogQuery.Where(x => x.CreationTime >= audiLogPageRequestDto.StartTime);
        }

        if (audiLogPageRequestDto.EndTime.HasValue)
        {
            auditLogQuery = auditLogQuery.Where(x => x.CreationTime <= audiLogPageRequestDto.EndTime);
        }

        if (audiLogPageRequestDto.CreatorId.HasValue)
        {
            auditLogQuery = auditLogQuery.Where(x => x.CreatorId == audiLogPageRequestDto.CreatorId);
        }

        if (audiLogPageRequestDto.AuditLogTypes != null && audiLogPageRequestDto.AuditLogTypes.Any())
        {
            auditLogQuery = auditLogQuery.Where(x => audiLogPageRequestDto.AuditLogTypes.Contains(x.AuditLogType));
        }

        var complexQuery = from auditLog in auditLogQuery
            join user in _userRepository.GetQueryable() on auditLog.CreatorId equals user.CreatorId
                into temp
            from user in temp.DefaultIfEmpty()
            select new AuditLogDto()
            {
                Id = auditLog.Id,
                ApiUrl = auditLog.ApiUrl,
                Method = auditLog.Method,
                Parameters = auditLog.Parameters,
                ExecutionDuration = auditLog.ExecutionDuration,
                ClientIpAddress = auditLog.ClientIpAddress,
                BrowserInfo = auditLog.BrowserInfo,
                AuditLogType = auditLog.AuditLogType,
                ExceptionMessage = auditLog.ExceptionMessage,
                Exception = auditLog.Exception,
                CreationTime = auditLog.CreationTime,
                CreatorUserName = user.UserName,
            };
        var count = auditLogQuery.Count();
        audiLogPageRequestDto.CurrentPage =
            audiLogPageRequestDto.CurrentPage < 1 ? 1 : audiLogPageRequestDto.CurrentPage;
        var list = complexQuery
            .OrderByDescending(x => x.Id)
            .Skip((audiLogPageRequestDto.CurrentPage - 1) * audiLogPageRequestDto.PageSize)
            .Take(audiLogPageRequestDto.PageSize)
            .ToList();
        result.AuditLogs = list;
        result.CurrentPage = audiLogPageRequestDto.CurrentPage;
        result.PageSize = audiLogPageRequestDto.PageSize;
        result.TotalCount = count;
        return result;
    }

    /// <summary>
    /// 删除审核日志
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    public bool Delete(long id)
    {
        return _auditLogRepository.Delete(id) > 0;
    }
}